package com.yl.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.yl.common.core.domain.AjaxResult;
import com.yl.config.ShengWangUrlConfig;
import com.yl.mapper.SwRecordMapper;
import com.yl.service.ShengWangService;
import com.yl.service.SwRecordService;
import com.yl.utils.HttpClientUtil;
import com.yl.utils.ShengWangUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ShengWangServiceImpl implements ShengWangService {
    private static final Logger log = LoggerFactory.getLogger(ShengWangServiceImpl.class);
    @Resource
    ShengWangUrlConfig shengWangUrlConfig;
    @Resource
    SwRecordService swRecordService;
    @Resource
    SwRecordMapper swRecordMapper;


    /**
     * 获取云端录制资格
     *
     * @param cname 频道名
     * @param uid   字符串内容为云端录制服务在频道内使用的 UID，用于标识频道内的录制服务，例如 "527841"。字符串内容需满足以下条件：
     * @return 一个 Resource ID 只能用于一次云端录制服务。
     * @author : y
     * @date :  2024/7/11 14:16
     **/
    @Override
    public String getAcquire(String cname, String uid) {
        // 获取token
        String token = ShengWangUtils.getToken(shengWangUrlConfig.getCustomerKey(), shengWangUrlConfig.getCustomerSecret());
        System.out.println("获取录制资格header 获取token=" + token);
        String url = shengWangUrlConfig.getCommonUrl() + shengWangUrlConfig.getAppid() + "/cloud_recording/acquire";
        HashMap<String, Object> map = new HashMap<>(16);
        map.put("cname", cname);
        map.put("uid", uid);
        HashMap<String, Object> clientRequestMap = new HashMap<>(16);
        /***
         * 0-实时音视频录制。
         * 1-：页面录制。
         * 2 单流录制模式，且开启延时转码或延时混音。
         * 延时转码：录制服务会在录制后 24 小时内（特殊情况下会到 48 小时以上）对录制文件进行转码生成 MP4 文件，并将 MP4 文件上传至你指定的第三方云存储。该场景仅适用于单流录制模式。
         * 延时混音：录制服务会在录制结束后 24 小时内（特殊情况下会到 48 小时以上）将指定频道内所有 UID 的录制文件合并并转码生成一个 MP3/M4A/AAC 文件，并将文件上传至你指定的第三方云存储。该场景仅适用于音频单流不转码录制模式。
         * **/
        clientRequestMap.put("scene", 0);
        //  resourceExpiredHour 云端录制 RESTful API 的调用时效。从成功开启云端录制并获得 sid （录制 ID）后开始计算。单位为小时。
        clientRequestMap.put("resourceExpiredHour", 24);
        map.put("clientRequest", clientRequestMap);
        String paramString = JSONObject.toJSONString(map);
        try {
            log.info("获取录制资格【入参】===uid -{};\n url - {};\nparamString - {};", uid, url, paramString);
            Map postJson = HttpClientUtil.sendShengWangPostJson(url, paramString, token);
            log.info("获取录制资格【返参】 uid -{}, result -  {}", uid, postJson);
            String resourceId = postJson.get("resourceId").toString();
            return resourceId;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 开启录制
     *
     * @return cname  string   录制的频道名。
     * uid  string  字符串内容为云端录制服务在 RTC 频道内使用的 UID，用于标识频道内的录制服务。
     * resourceId string   云端录制资源 Resource ID。使用这个 Resource ID 可以开始一段云端录制。这个 Resource ID 的有效期为 5 分钟，超时需要重新请求。
     * sid   string     录制 ID。成功开始云端录制后，你会得到一个 Sid （录制 ID）。该 ID 是一次录制周期的唯一标识。
     * @author : y
     * @date :  2024/7/11 14:15
     **/
    @Override
    public AjaxResult start(String cname, String uid, String userToken) {
        // 开启录制前查询 之前的录制有没有结束 没有则主动给停止
        swRecordMapper.updateUnEnd(cname);
        // 获取token
        String token = ShengWangUtils.getToken(shengWangUrlConfig.getCustomerKey(), shengWangUrlConfig.getCustomerSecret());
        String resourceid = getAcquire(cname, uid);
        /***
         * resourceid 获取录制资格id 每次开始重新获取
         *  mode :{
         *    individual 单流录制模式
         *    mix:合流录制模式。
         *    web：页面录制模式。
         *  }
         * **/
        //本次录制采用 单流录制模式
        String url = shengWangUrlConfig.getCommonUrl() + shengWangUrlConfig.getAppid() + "/cloud_recording/resourceid/" + resourceid + "/mode/individual/start";
        HashMap<String, Object> paramMap = new HashMap<>(16);
        HashMap<String, Object> clientRequestMap = new HashMap<>(16);
        // 第三方云存储的配置项。
        HashMap<String, Object> storageConfigMap = new HashMap<>(16);
        paramMap.put("cname", cname);
        paramMap.put("uid", uid);
        clientRequestMap.put("token", userToken);
        // 1：Amazon S3
        // 2：阿里云
        // 3：腾讯云
        // 5：Microsoft Azure
        // 6：谷歌云
        // 7：华为云
        // 8：百度智能云
        storageConfigMap.put("vendor", 2);
        // region 第三方云存储指定的地区信息。
        storageConfigMap.put("region", 3);
        storageConfigMap.put("bucket", shengWangUrlConfig.getAliBucket());
        storageConfigMap.put("accessKey", shengWangUrlConfig.getAliAccessKey());
        storageConfigMap.put("secretKey", shengWangUrlConfig.getAliSecretKey());
        ArrayList<String> fileUrl = new ArrayList<>();
        fileUrl.add("leaderVideoFile");
        fileUrl.add(cname);
        storageConfigMap.put("fileNamePrefix", fileUrl);
        clientRequestMap.put("storageConfig", storageConfigMap);
        // 设置最大空闲时间
        HashMap<String, Object> recordingConfigMap = new HashMap<>(16);
        // 最大设置30天 单位秒  目前设置2小时
        recordingConfigMap.put("maxIdleTime", 240);
        recordingConfigMap.put("subscribeUidGroup", 2);
        // 媒体流的输出模式。详见媒体流输出模式。 原始编码模式。适用于单流音频不转码录制。仅订阅音频时
        recordingConfigMap.put("streamMode", "original");
        // 频道场景。0：通信场景。1：直播场景。
        recordingConfigMap.put("channelType", 1);
        // 订阅的媒体流类型。0：仅订阅音频。适用于智能语音审核场景。 1：仅订阅视频。2：订阅音频和视频。
        recordingConfigMap.put("streamTypes", 0);
        clientRequestMap.put("recordingConfig", recordingConfigMap);
        paramMap.put("clientRequest", clientRequestMap);
        try {
            String paramString = JSONObject.toJSONString(paramMap);
            log.info("开始录制调用POST  【入参】uid -  {} ;\n param={} \nurl - {} ", uid, paramString, url);
            Map map = HttpClientUtil.sendShengWangPostJson(url, paramString, token);
            // 返回 uname, uid .resourceId, sid
            log.info("开始录制调用POST 【返参】 uid -  {} ;\n result - {}", uid, map);
            map.put("luZhiUid", uid);
            swRecordService.save(cname, uid, resourceid, map.get("sid") == null ? "" : map.get("sid").toString());
            return AjaxResult.success(map);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 停止录制
     *
     * @param cname
     * @param uid
     * @author : y
     * @date :  2024/7/11 14:56
     */
    @Override
    public String stop(String cname, String uid, String resourceid, String sid) {
        // 获取 token
        String token = ShengWangUtils.getToken(shengWangUrlConfig.getCustomerKey(), shengWangUrlConfig.getCustomerSecret());
        String url = shengWangUrlConfig.getCommonUrl() + shengWangUrlConfig.getAppid()
                + "/cloud_recording/resourceid/" + resourceid + "/sid/" + sid + "/mode/individual/stop";
        HashMap<String, Object> paramMap = new HashMap<>(16);
        HashMap<String, Object> clientRequestMap = new HashMap<>(16);
        paramMap.put("cname", cname);
        paramMap.put("uid", uid);
        // 设置 stop 方法的响应机制： true 异步 ，调用stop后立即返回响应，
        // false 同步，调用stop后，你需要等待所有的录制文件上传至三方存储后会受到响应，声网预期上传时间不超过 20 秒，如果上传超时，你会收到错误码 50。
        clientRequestMap.put("async_stop", true);
        paramMap.put("clientRequest", clientRequestMap);
        try {
            String paramString = JSONObject.toJSONString(paramMap);
            log.info("结束录制===调用POST===【入参】==== cname- {},uid - {};\n param={} \n url - {} ", cname, uid, paramString, url);
            Map postJson = HttpClientUtil.sendShengWangPostJson(url, paramString, token);
            // 返回 uname, uid .resourceId, sid
            log.info("结束录制===调用POST==【返参】==uid - {};\n result:{}", uid, postJson);
            if (postJson.containsKey("code")) {
                if (postJson.get("code").equals(200)) {
                    log.info("结束录制返回参数code=200 打印日志 - {}", postJson);
                    // 获取到文件名称
                    if (postJson.containsKey("serverResponse")) {
                        HashMap<String, Object> hashMap = (HashMap<String, Object>) postJson.get("serverResponse");
                        List<Map<String, Object>> mapList = (List<Map<String, Object>>) hashMap.get("fileList");
                        log.info("获取到结束录制返回参数的 fileList={}", mapList);
                        if (mapList != null && mapList.size() != 0) {
                            Map<String, Object> map = mapList.get(0);
                            log.info("获取到文件信息=={}", map);
                            return map.get("fileName").toString();
                        }
                    }
                } else if (postJson.get("code").equals(435)) {
                    log.info("没有录制文件产生。频道内没有用户发流，无录制对象。 uid - {},resourceid - {} , sid - {}", uid, resourceid, sid);
                    return null;
                } else if (postJson.get("code").equals(404)) {
                    log.info("声网返回： 服务器无法根据请求找到资源（网页）。 uid - {},resourceid - {} , sid - {}", uid, resourceid, sid);
                    return null;
                } else {
                    log.info("录制失败。code - {}; uid - {},resourceid - {} , sid - {}", postJson.get("code"), uid, resourceid, sid);
                    return null;
                }
            } else {
                System.out.println("停止录制没有 code字段======");
                if (postJson.containsKey("serverResponse")) {
                    HashMap<String, Object> hashMap = (HashMap<String, Object>) postJson.get("serverResponse");
                    List<Map<String, Object>> mapList = (List<Map<String, Object>>) hashMap.get("fileList");
                    log.info("获取到结束录制返回参数的 fileList={}", mapList);
                    if (mapList != null && mapList.size() != 0) {
                        Map<String, Object> map = mapList.get(0);
                        log.info("获取到文件信息=={}", map);
                        return map.get("fileName").toString();
                    }
                }

            }


        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询录制状态
     *
     * @param resourceid
     * @param sid
     * @author : y
     * @date :  2024/7/11 21:19
     */
    @Override
    public AjaxResult query(String resourceid, String sid) {
        // 获取 token
        String token = ShengWangUtils.getToken(shengWangUrlConfig.getCustomerKey(), shengWangUrlConfig.getCustomerSecret());
        log.info("查询录制状态={}", token);
        String url = shengWangUrlConfig.getCommonUrl() + shengWangUrlConfig.getAppid()
                + "/cloud_recording/resourceid/" + resourceid + "/sid/" + sid + "/mode/individual/query";
        log.info("查询录制状态====url={},\ntoken={}\n", url, token);
        Map postJson = HttpClientUtil.doGetShengWangNotParam(url, token);
        // 返回 uname, uid .resourceId, sid
        log.info("查询录制状态返回参数={}", postJson);
        if (postJson.get("code").equals("404")) {
            return AjaxResult.error("请求仅在会话内有效。录制启动错误，或录制已结束");
        } else {
            return AjaxResult.success(postJson.get("serverResponse"));
        }
    }

    /**
     *
     * 延时混音配置
     * @author : y
     * @date :  2024/7/12 15:40
     **/
    // public AjaxResult start(String cname, Long uid, String userToken) {
    //     // 获取token
    //     String token = ShengWangUtils.getToken(shengWangUrlConfig.getCustomerKey(), shengWangUrlConfig.getCustomerSecret());
    //     log.info("开始录制获取录制资格token={}", token);
    //     String resourceid = getAcquire(cname, uid);
    //     /***
    //      * resourceid 获取录制资格id 每次开始重新获取
    //      *  mode :{
    //      *    individual 单流录制模式
    //      *    mix:合流录制模式。
    //      *    web：页面录制模式。
    //      *  }
    //      * **/
    //     //本次录制采用 单流录制模式
    //     String url = shengWangUrlConfig.getCommonUrl() + shengWangUrlConfig.getAppid() + "/cloud_recording/resourceid/" + resourceid + "/mode/individual/start";
    //     HashMap<String, Object> paramMap = new HashMap<>(16);
    //     HashMap<String, Object> clientRequestMap = new HashMap<>(16);
    //     // 第三方云存储的配置项。
    //     HashMap<String, Object> storageConfigMap = new HashMap<>(16);
    //     paramMap.put("cname", cname);
    //     paramMap.put("uid", uid.toString());
    //     clientRequestMap.put("token", userToken);
    //     // 1：Amazon S3
    //     // 2：阿里云
    //     // 3：腾讯云
    //     // 5：Microsoft Azure
    //     // 6：谷歌云
    //     // 7：华为云
    //     // 8：百度智能云
    //     storageConfigMap.put("vendor", 2);
    //     // region 第三方云存储指定的地区信息。
    //     storageConfigMap.put("region", 3);
    //     storageConfigMap.put("bucket", shengWangUrlConfig.getAliBucket());
    //     storageConfigMap.put("accessKey", shengWangUrlConfig.getAliAccessKey());
    //     storageConfigMap.put("secretKey", shengWangUrlConfig.getAliSecretKey());
    //     ArrayList<String> fileUrl = new ArrayList<>();
    //     fileUrl.add("leaderVideoFile");
    //     fileUrl.add(cname);
    //     storageConfigMap.put("fileNamePrefix", fileUrl);
    //     clientRequestMap.put("storageConfig", storageConfigMap);
    //
    //     // 延时转码或延时混音下，生成的录制文件的配置项。----设置转MP3文件
    //     HashMap<String, Object> transcodeOptionsMap = new HashMap<>(16);
    //     HashMap<String, Object> transConfigMap = new HashMap<>(16);
    //     HashMap<String, Object> containerMap = new HashMap<>(16);
    //     HashMap<String, Object> audio = new HashMap<>(16);
    //     audio.put("sampleRate","48000");
    //     audio.put("bitrate","48000");
    //     audio.put("channels","2");
    //     transConfigMap.put("transMode","audioMix");
    //     containerMap.put("format","mp3");
    //     transcodeOptionsMap.put("transConfig",transConfigMap);
    //     transcodeOptionsMap.put("container",containerMap);
    //     transcodeOptionsMap.put("audio",audio);
    //     clientRequestMap.put("transcodeOptions", transcodeOptionsMap);
    //     // 设置最大空闲时间
    //     HashMap<String, Object> recordingConfigMap = new HashMap<>(16);
    //     // 最大设置30天 单位秒  目前设置2小时
    //     recordingConfigMap.put("maxIdleTime",7200);
    //     recordingConfigMap.put("subscribeUidGroup",2);
    //     // 媒体流的输出模式。详见媒体流输出模式。 原始编码模式。适用于单流音频不转码录制。仅订阅音频时
    //     recordingConfigMap.put("streamMode","original");
    //     // 频道场景。0：通信场景。1：直播场景。
    //     recordingConfigMap.put("channelType",1);
    //     // 订阅的媒体流类型。0：仅订阅音频。适用于智能语音审核场景。 1：仅订阅视频。2：订阅音频和视频。
    //     recordingConfigMap.put("streamTypes",0);
    //
    //     clientRequestMap.put("recordingConfig", recordingConfigMap);
    //     // 设置延时转码或延时混音下
    //     HashMap<String, Object> appsCollection = new HashMap<>(16);
    //     appsCollection.put("combinationPolicy","postpone_transcoding");
    //     clientRequestMap.put("appsCollection", appsCollection);
    //
    //     paramMap.put("clientRequest", clientRequestMap);
    //     try {
    //         String paramString = JSONObject.toJSONString(paramMap);
    //         log.info("开始录制参数 url={},\n参数={},\nToken={}", url, paramString, token);
    //         Map map = HttpClientUtil.sendShengWangPostJson(url, paramString, token);
    //         // 返回 uname, uid .resourceId, sid
    //         log.info("开始录制返回参数={}", map);
    //         return AjaxResult.success(map);
    //     } catch (IOException e) {
    //         e.printStackTrace();
    //     }
    //     return null;
    // }
}
